const randomString = () => Math.random().toString(36).substring(7).split("").join(".");

function createStore(reducer) {
  let state, listeners = [], currnetReducer = reducer;
  let getState = function getState() {
    return state;
  };
  let dispatch = function dispatch(action) {
    if (typeof action !== 'object' && Object.prototype.toString.call(action) !== '[object Object]') {
      throw new TypeError('Expect the action to be a object.');
    }
    if (action.type === undefined) {
      throw new TypeError('action.type not allowed to be a undefined.');
    }
    // 每一次 dispatch 都会执行 reducer
    state = currnetReducer(state, action);
    // 执行事件池中的事件
    listeners.forEach(cb => cb());
    return action;
  };
  let subscribe = function subscribe(listener) {
    if (typeof listener !== 'function') {
      throw new TypeError('Expect the listener to be a function.');
    }
    // 保留到事件池
    listeners.push(listener);
    // 返回一个 unsubscribe 方法，用来移除事件
    return () => {
      let index = listeners.indexOf(listener);
      listeners.splice(index, 1);
    };
  };
  // 手动 dispatch ，目的是初始化数据
  dispatch({ type: randomString() });
  let store = {
    getState,
    dispatch,
    subscribe,
  };
  return store;
}

export function combineReducers(reducers) {
  // 模块
  let finalKeys = Object.keys(reducers)

  // 合并reducer，返回的也是一个 reducer
  return (state = {}, action) => {
    // 形参 state 拿到的是总状态

    let nextState = { ...state }

    finalKeys.forEach(key => {
      // key 就是 reducer 的模块名

      let reducer = reducers[key]

      // reducer模块需要接收的实参是模块下的状态
      nextState[key] = reducer(state[key], action)
    })

    // 返回总状态
    return nextState
  }
}

/**
 * {
 *    [key]: () => {
 *      dispatch()
 *    }
 * }
 */
function bindActionCreator(actionCreator, dispatch) {
  return function (...args) {
    return dispatch(actionCreator.apply(this, args))
  }
}

export function bindActionCreators(actionCreators, dispatch) {
  if (typeof actionCreators === 'function') {
    return bindActionCreator.apply(this, [])
  }
  if (typeof actionCreators !== 'object') {
    throw new TypeError('expect object!')
  }

  let boundlerAction = {}
  for (let key in actionCreators) {
    // key 就是 actionCreators 中的函数名
    let rawActionCreator = actionCreators[key]
    boundlerAction[key] = bindActionCreator(rawActionCreator, dispatch)
  }
  return boundlerAction
}

/**
 * dispatch({
 *  type: 'VOTE_OPP'
 * })
 */

export { createStore };
